# Common functions and class that can be used by all djips applications.
from django.shortcuts import render_to_response
from django.db.models.query import CollectedObjects
from django.http import HttpResponseRedirect

from settings import INSTALLED_APPS
from settings import MEDIA_URL
from settings import ADMIN_BASE_URL

from models import Folder
from core import make_menu

class Info:
    """ Defines an element displayed in the info list in the main page
    of yaps common administration.

    We could have used model to store it in the database but most of these
    information are volatile and dynamic.
    """

    def __init__(self,
		 title = None,
		 url = None,
		 text = None):
	self.title = title
	self.url = url
	self.text = text

def find_template_folder(function):
    """ Finds template folder for a given function.
    Djips views package must have a 'template_folder'
    variable defined if they use the @djips_view
    decorator.
    """

    module = function.__module__

    try:
        exec 'from %s import template_folder' % module
    except:
        # This Djips module is not correct.
        return

    return template_folder

def user_has_permission(request, permission):
    """ Checks if the user has the given permission.
    """
    user = request.user
    if permission == 'Anonymous':
        return True
    if permission == 'Admin':
        if user.is_staff:
            return True
    elif permission == 'Authenticated':
        if user.is_authenticated:
            return True
    return False

def djips_view(permission):
    """ This is a simple decorator that is used for Djips
    views.
    It checks if the current user can access the view, adds
    some informations sent to the template and makes the template
    path shorter.

    It takes one argument, permission that can be set to:
    - Anonymous for public views, 
    - Authenticated for logged-in user views
    - Admin for views that can only be accessed by staff users.
    """
    def _djips_view(function):
        def __djips_view(*args, **kwargs):
            # First we check the user's permissions.
            request = args[0]
            redirect_url = ADMIN_BASE_URL + '/login/?next=' + \
                           request.path

            if not user_has_permission(request, permission):
                return HttpResponseRedirect(redirect_url)
                
            # The function shall return the template name
            # and a list of data to pass to the template.
            res = function(*args, **kwargs)
            try:
                template, data = res
            except:
                # Ok, we might have sent a request directly.
                return res

            template_folder = find_template_folder(function)
            if not template_folder:
                return

            if request.user.is_authenticated():
                data['user'] = request.user
                data['menu'] = make_menu(request.path)

            if 'next' in request.GET:
                data['login_required'] = True

            data['admin_base_url'] = ADMIN_BASE_URL
            data['media_url'] = MEDIA_URL

            return render_to_response(template_folder + template, data)

        return __djips_view
    return _djips_view

def get_related_objects(obj):
    """ Gets all objects related to an object.
    This shall mainly be used to warn the user before he deletes
    an object (for example 'This tag is used by those images, those blog
    posts ...) 
    """
    related = CollectedObjects()
    obj._collect_sub_objects(related)

    returned_values = {}
    relation_dict = dict(related.items())

    for related_type in relation_dict:
	# Checks that we did not specify to not show those items.
	if 'filter_from_deletion_warning' in dir(related_type):
	    if related_type.filter_from_deletion_warning:
		continue

	related_items = relation_dict[related_type]

	# Eventually filter out the current object and transforms
	# the dictionnary into a list (we do not need the ids.
	if related_type == type(obj):
	    items = [related_items[obj_id] for obj_id in related_items
		     if obj_id != obj.id]
	else:
	    items = [related_items[obj_id] for obj_id in related_items]

	if items:
	    returned_values[related_type.__name__] = items

    return returned_values
